package main

import (
	"fmt"
	"os"
	"strings"

	"gitee.com/libbylg/pkgr/repo"
)

type PrinterContext struct {
	Label  *repo.ModuleLabel
	Detial *repo.ModuleVersionDescription
}

func PrintLABEL(file *os.File, ctx *PrinterContext) {
	fmt.Fprintf(file, "%-19v %v\n", "LABEL", ctx.Label.String())
}

func PrintMODULENAME(file *os.File, ctx *PrinterContext) {
	fmt.Fprintf(file, "%-19v %v\n", "MODULENAME", ctx.Label.ModuleName)
}

func PrintMODULEVERSION(file *os.File, ctx *PrinterContext) {
	fmt.Fprintf(file, "%-19v %v\n", "MODULEVERSION", ctx.Label.ModuleVersion)
}

func PrintSTATUS(file *os.File, ctx *PrinterContext) {
	//fmt.Fprintf(file, "%-19v %v\n", "STATUS", label.ModuleName)
}

func PrintDESCCRIPTION(file *os.File, ctx *PrinterContext) {
	if ctx.Detial == nil {
		return
	}

	fmt.Fprintf(file, "%-19v %v\n", "DESCCRIPTION", ctx.Detial.Description)
}

//func PrintLICENSE(file *os.File, ctx *PrinterContext) {
//	if ctx.Detial == nil {
//		return
//	}
//
//	fmt.Fprintf(file, "%-19v %v\n", "LICENSE", ctx.Detial.License)
//}

func PrintPACKAGE(file *os.File, ctx *PrinterContext) {
	if ctx.Detial == nil {
		return
	}

	for _, pkg := range ctx.Detial.ModulePackages {
		fmt.Fprintf(file, "%-19v %v %v %v %v %v\n", "PACKAGE", pkg.PackageTags, pkg.PackageName, pkg.PackageInner, pkg.DownloadURL, pkg.HASH)
	}
}

//func PrintIMPORTAS(file *os.File, ctx *PrinterContext) {
//	if ctx.Detial == nil {
//		return
//	}
//
//	fmt.Fprintf(file, "%-19v %v\n", "IMPORTAS", ctx.Detial.ImportAs)
//}

func PrintREQUIRED(file *os.File, ctx *PrinterContext) {
	if ctx.Detial == nil {
		return
	}

	for _, req := range ctx.Detial.RequiredModules {
		fmt.Fprintf(file, "%-19v %v\n", "REQUIRED", req)
	}
}

//func PrintTRAINVERSION(file *os.File, ctx *PrinterContext) {
//	if ctx.Detial == nil {
//		return
//	}
//
//	fmt.Fprintf(file, "%-19v %v\n", "TRAINVERSION", ctx.Detial.TrainVersion)
//}
//
//func PrintTRAINMODULENAME(file *os.File, ctx *PrinterContext) {
//	if ctx.Detial == nil {
//		return
//	}
//
//	fmt.Fprintf(file, "%-19v %v\n", "TRAINMODULENAME", ctx.Detial.TrainModuleName)
//}
//
//func PrintTRAINMODULEVERSION(file *os.File, ctx *PrinterContext) {
//	if ctx.Detial == nil {
//		return
//	}
//
//	fmt.Fprintf(file, "%-19v %v\n", "TRAINMODULEVERSION", ctx.Detial.TrainModuleVersion)
//}

type PrinterMapper struct {
	Name string
	Func func(file *os.File, ctx *PrinterContext)
}

var ALL_ATTR_PRINTER_MAPPERS = []PrinterMapper{
	{"l", PrintLABEL},
	{"n", PrintMODULENAME},
	{"v", PrintMODULEVERSION},
	{"st", PrintSTATUS},
	{"desc", PrintDESCCRIPTION},
	//{"lic", PrintLICENSE},
	{"p", PrintPACKAGE},
	//{"i", PrintIMPORTAS},
	{"req", PrintREQUIRED},
	//{"tv", PrintTRAINVERSION},
	//{"tmn", PrintTRAINMODULENAME},
	//{"tmv", PrintTRAINMODULEVERSION},
}

type CmdQueryOptions struct {
	Label    string
	Keywords string
}

// NewCmdQueryOptions 识别命令行选项.
// pkgr query   LABEL Keywords
func NewCmdQueryOptions(argv []string) (*CmdQueryOptions, error) {
	// 检查参数数量
	if len(argv) < 4 {
		return nil, fmt.Errorf("the required parameter is missing, try -h for help")
	}

	// 初始化默认值
	opt := &CmdQueryOptions{
		Label:    "",
		Keywords: "",
	}

	pos := 0

	// 读取选项
	for index := 2; index < len(argv); index++ {
		// 遇到无法识别的选项
		if strings.HasPrefix(argv[index], "-") {
			return nil, fmt.Errorf("unsupported options `%v'", argv[index])
		}

		// 识别 Label 参数
		if pos == 0 {
			opt.Label = strings.TrimSpace(argv[index])
			pos++
			continue
		}

		// 识别 Keywords 参数
		if pos == 1 {
			opt.Keywords = strings.TrimSpace(argv[index])
			pos++
			continue
		}

		return nil, fmt.Errorf("unsupported option `%v'", argv[index])
	}

	if opt.Label == "" {
		return nil, fmt.Errorf("missing the query label parameter, try -h for help")
	}

	if opt.Keywords == "" {
		return nil, fmt.Errorf("missing the query attributes parameter, try -h for help")
	}

	return opt, nil
}

func CmdQuery(argv []string) int {
	opt, err := NewCmdQueryOptions(argv)
	if err != nil {
		ERROR("Load option for `%v' failed: %v", "query", err.Error())
		return 1
	}

	keywords := make([]string, 0)
	if opt.Keywords == "*" || opt.Keywords == "all" {
		for _, printer := range ALL_ATTR_PRINTER_MAPPERS {
			keywords = append(keywords, printer.Name)
		}
	} else {
		keywords = strings.Split(opt.Keywords, ":")
		if len(keywords) == 0 {
			ERROR("No keywords specified")
			return 0
		}
	}

	printerMapping := make(map[string]PrinterMapper)
	for _, printer := range ALL_ATTR_PRINTER_MAPPERS {
		printerMapping[printer.Name] = printer
	}

	ignoreCount := 0
	for _, item := range keywords {
		if _, exist := printerMapping[item]; !exist {
			WARNI("Unsupported query keyword `%v', ignored", item)
		}
	}

	if ignoreCount == len(keywords) {
		ERROR("No valid query keyword specified, nothing need to print")
		return 0
	}

	// 校验模块和版本号
	moduleLabel, err := repo.ParseModuleLabel(opt.Label)
	if err != nil {
		ERROR("Invalid module label `%v': %v", opt.Label, err.Error())
		return 1
	}

	// 依赖于 module-version 文件的信息
	var moduleDetail *repo.ModuleVersionDescription = nil
	if repo.PathIsDir(repo.PKGREPO) {
		moduleDetail, err = repo.ReadModuleVersionDescription(moduleLabel.String())
		if err != nil {
			WARNI("Load module version file for `%v' failed: %v", moduleLabel.String(), err)
		}
	}

	ctx := &PrinterContext{Label: moduleLabel, Detial: moduleDetail}

	// 准备输出
	for _, item := range keywords {
		printer, exist := printerMapping[item]
		if !exist {
			continue
		}

		printer.Func(os.Stdout, ctx)
	}

	return 0
}
